# $Id: views.py 7557b5d4d82b 2012/12/02 09:07:16 pgurumur $
# Copyright (c) 2009 Prabhu Gurumurthy  <pgurumur@gmail.com>
# 
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

__version__ = "$Revision: 7557b5d4d82b $"
__author__ = "$Author: pgurumur $"

from django.conf import settings
from django.conf.urls.defaults import patterns
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper
from django.forms import ValidationError
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.shortcuts import render_to_response
from django.template import loader
from django.views.decorators.csrf import csrf_exempt, csrf_protect

from djanet import utils
from djanet.db import netdb, query
from djanet.forms import LoginForm, WhoisForm
from djanet.lib import exception, ip, log, stdlib
from djanet.ui.forms import RFC4193Form
from djanet.utils import grid, http
from djanet.utils.decorators import superuser_required, json_response
from djanet.utils.decorators import is_authenticated, mlogin_required

ValidDevice = lambda device: device.monitored and device.snmp_target

@is_authenticated
def djanet_login(request):
   log = utils.loghandle(djanet_login.__name__)
   retval = None
   userLoginForm = None
   if request.method == 'GET':
      userLoginForm = LoginForm()
      retval = render_to_response(settings.MTEMPLATES['LOGIN'],
            utils.get_context(request, title = 'login',
               loginform = userLoginForm, login_action = reverse(djanet_login)))
      request.session.set_test_cookie()
   elif request.method == 'POST':
      userLoginForm = LoginForm(request.POST)
      if userLoginForm.is_valid():
         username = userLoginForm.cleaned_data.get('djanet_username')
         password = userLoginForm.cleaned_data.get('djanet_password')

         url = reverse(djmobile_neteng)
         referer = request.META['HTTP_REFERER']
         nextval = referer.split('=/')
         if len(nextval) == 2:
            url = '/' + nextval[1]

         try:
            user = authenticate(username = username.strip(),
                  password = password.strip())
         except exception.AuthError, message:
            log(str(message))
            retval = utils.djanet_error(request, utils.FORBIDDEN,
                  login = reverse(djanet_login), error = message)
         else:
            if user.is_active:
               login(request, user)
               request.session.set_expiry(settings.SESSION_EXPIRY)
               retval = HttpResponseRedirect(url)
            else:
               retval = utils.djanet_error(request, utils.FORBIDDEN,
                     login = reverse(djanet_login),
                     error = 'User is marked inactive in the database')
      else:
         retval = utils.djanet_error(request, utils.FORBIDDEN,
               login = reverse(djanet_login))
   else:
      retval = utils.djanet_error(request, utils.NOTALLOWED,
            error = 'Invalid method %s requested' %request.method)

   return retval

def djanet_logout(request):
   retval = None
   if request:
      logout(request)
      retval = HttpResponseRedirect(reverse(djanet_login))

   return retval

@login_required
@superuser_required
def djanet_rfc4193(request):
   log = utils.loghandle(djanet_rfc4193.__name__)
   retval = None
   if request.method == 'GET':
      ipv6form = RFC4193Form()
      retval = render_to_response(settings.TEMPLATES['RFC4193'],
            context_instance = utils.get_context(request, rfcform = ipv6form,
               ipv6_action = reverse(djanet_rfc4193)))
   elif request.method == 'POST':
      retval = {}
      retval["success"] = False
      ipv6form = RFC4193Form(request.POST)
      if ipv6form.is_valid():
         address = ipv6form.GetAddress(request.POST)
         if address:
            retval["success"] = True
            retval["address"] = str(address)

      retval = http.JSONResponse(retval)

   return retval

@login_required
@superuser_required
def djanet_neteng(request):
   retval = None
   if request.method == 'GET':
      retval = render_to_response(settings.TEMPLATES['BGPPEER'],
            utils.get_context(request))
   else:
      retval = utils.djanet_error(request, utils.FORBIDDEN,
            error = 'Invalid method %s requested' %request.method)

   return retval

@login_required
def djanet_whois(request):
   log = utils.loghandle(djanet_whois.__name__)
   retval = None
   if request.method == 'GET':
      whoisform = WhoisForm()
      retval = render_to_response(settings.TEMPLATES['WHOIS'],
            context_instance = utils.get_context(request, whoisform = whoisform,
               formtitle = 'whois', whois_action = reverse(djanet_whois)))
   elif request.method == 'POST':
      retval = {}
      whoisform = WhoisForm(request.POST)
      try:
         if whoisform.is_valid():
            retval['asnumber'] = whoisform.cleaned_data.get('asnumber')
            retval['ipaddress'] = whoisform.cleaned_data.get('ipaddress')
            retval['server'] = whoisform.cleaned_data.get('whoisserver')
            temp = whoisform.GetInfo(retval)
            if temp:
               retval['whoisinfo'] = temp
            else:
               retval['whoisinfo'] = ''
      except ValidationError, message:
         log.info(message)
      else:
         retval['success'] = True
         retval = http.JSONResponse(retval)

   return retval

@json_response
def djanet_getmask(request):
   log = utils.loghandle(djanet_getmask.__name__)
   retval = {}
   retval['success'] = False
   if request.method == 'POST':
      length = int(request.POST["length"])
      masktype = int(request.POST["type"])
      wildcard = False

      if masktype == 0:
         wildcard = True
      elif masktype == 1:
         wildcard = False

      maskval = None
      try:
         maskval = stdlib.netmask4(length, wildcard)
      except ValueError, message:
         retval["error"] = message
      else:
         retval["success"] = True
         retval["netmask"] = str(maskval)

   return retval

def djanet_test(request):
   return HttpResponse('Hello World!')

@json_response
def djanet_bgppeer(request):
   log = utils.loghandle(djanet_bgppeer.__name__)
   retval = {}
   if request.method == 'POST':
      rp = None
      start = 0
      if request.POST["rp"]:
         rp = int(str(request.POST["rp"]))

      if rp is None:
         rp = 10


      page = int(str(request.POST["page"]))
      start = (page - 1) * rp
      end = None
      if page:
         end = page * rp
      else:
         end = rp

      query = None
      if request.POST["qtype"] == "peer":
         query = request.POST["query"]

      count = 0
      retval["rows"] = []
      retval["page"] = request.POST["page"]
      iterobj = None
      if query:
         iterobj = netdb.Bgppeering.objects.filter(bgppeerid = query)
      else:
         iterobj = netdb.Bgppeering.objects.all()

      for ix in iterobj:
         count += 1

      retval["total"] = count

      for ix in iterobj[start:end]:
         obj = {}
         address = None
         asnum = None
         try:
            address = ip.ip(str(ix))
            asnum = netdb.Entity.objects.get(id = ix.entity).asnumber
         except exception.IPError, message:
            pass
         except ObjectDoesNotExist:
            pass
         else:
            if int(address) and asnum:
               obj["id"] = str(address)
               temp = []
               temp.append(str(address))
               temp.append(str(ix.Device))
               temp.append(str(ix.Device.ip))
               temp.append(str(asnum))
               obj["cell"] = temp
               retval["rows"].append(obj)


   return retval

def djanet_nagios(request):
   hosts = []
   bgphosts = []
   for device in netdb.Device.objects.all():
      items = {}
      if ValidDevice(device):
         items["name"] = str(device)
         items["group"] = str(device.Site)
         items["contact"] = "netops@silverspringnet.com"
         if device.ip:
            items["address"] = str(device.ip)
            hosts.append(items)

   for peer in netdb.Bgppeering.objects.all():
      items = {}
      if peer.valid:
         if peer.monitored and ValidDevice(peer.Device):
            items["host"] = str(peer.Device.ip)
            items["site"] = str(peer.Device.Site)
            items["peer"] = str(peer)
            items["contact"] = "netops@silverspringnet.com"
            items["command"] = "check_bgppeer"
            items["community"] = str(peer.Device.community)
            bgphosts.append(items)

   response = HttpResponse(utils.template_string()(
      settings.TEMPLATES['NAGIOS'], utils.get_context(request,
         hosts = hosts, bgphosts = bgphosts)))

   return response

def djanet_checkbgp(request, device, bgppeer):
   log = utils.loghandle(djanet_checkbgp.__name__)
   flag = False
   retval = HttpResponse("false")
   if device and bgppeer:
      devip = None
      peerip = None

      try:
         devip = ip.ip(device)
      except exception.IPError, message:
         pass

      try:
         peerip = ip.ip(bgppeer)
      except exception.IPError, message:
         pass

      bgpdevice = None
      if devip and peerip:
         bgpdevice = query.GetDevice(devip)

      if bgpdevice and bgpdevice.monitored:
         for peer in netdb.Bgppeering.objects.filter(device = bgpdevice.id,
               monitored = 1).all():
            if str(peerip) == str(peer):
               flag = True
               break

      if flag:
         retval = HttpResponse("true")

   return retval

@mlogin_required
def djmobile_neteng(request):
   retval = None
   if request.method == 'GET':
      retval = render_to_response(settings.MTEMPLATES['NETENG'],
            utils.get_context(request, title = "neteng"))

   return retval

@mlogin_required
def djmobile_whois(request):
   log = utils.loghandle(djmobile_whois.__name__)
   retval = None
   if request.method == 'GET':
      whoisform = WhoisForm()
      retval = render_to_response(settings.MTEMPLATES['WHOIS'],
            utils.get_context(request, whoisform = whoisform,
               title = 'whois', whois_action = reverse(djmobile_whois)))
   elif request.method == 'POST':
      retval = {}
      whoisform = WhoisForm(request.POST)
      try:
         if whoisform.is_valid():
            retval['asnumber'] = whoisform.cleaned_data.get('asnumber')
            retval['ipaddress'] = whoisform.cleaned_data.get('ipaddress')
            retval['server'] = whoisform.cleaned_data.get('whoisserver')
            temp = whoisform.GetInfo(retval)
            if temp:
               retval['whoisinfo'] = temp
            else:
               retval['whoisinfo'] = ''
      except ValidationError, message:
         log.info(message)
      else:
         retval['success'] = True
         retval = http.JSONResponse(retval)

   return retval

@mlogin_required
def djmobile_list(request, table):
   log = utils.loghandle(djmobile_list.__name__)
   retval = None
   if request.method == 'GET':
      dblist = None
      title = None
      devtable = None
      if table:
         if table.lower() == "device":
            dblist = netdb.Device.objects.all()
            title = netdb.Device._meta.verbose_name
         elif table.lower() == "site":
            dblist = netdb.Site.objects.all()
            title = netdb.Device._meta.verbose_name

      retval = render_to_response(settings.MTEMPLATES['DBLIST'],
            utils.get_context(request, dblist = dblist, title = title))

   return retval
